package com.liang.subject.domain.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.liang.subject.common.entity.PageDTO;
import com.liang.subject.common.enums.SubjectLikedStatusEnum;
import com.liang.subject.domain.entity.SubjectLikedBO;
import com.liang.subject.domain.entity.SubjectLikedMessage;
import com.liang.subject.domain.service.SubjectLikedDomainService;
import com.liang.subject.infra.basic.entity.SubjectInfo;
import com.liang.subject.infra.basic.entity.SubjectLiked;
import com.liang.subject.infra.basic.service.SubjectInfoService;
import com.liang.subject.infra.basic.service.SubjectLikedService;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service
public class SubjectLikedDomainServiceImpl implements SubjectLikedDomainService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private SubjectLikedService subjectLikedService;
    @Resource
    private SubjectInfoService subjectInfoService;
    @Resource
    private RocketMQTemplate rocketMQTemplate;

    private static final String SUBJECT_LIKED_PREFIX = "subject.liked";
    private static final String SUBJECT_LIKED_COUNT_PREFIX = "subject.liked.count";
    private static final String SUBJECT_LIKED_DETAIL_KEY = "subject.liked.detail";

    @Override
    public void save(SubjectLikedBO subjectLikedBO) {
        Integer status = subjectLikedBO.getStatus();
        Long subjectId = subjectLikedBO.getSubjectId();
        String likeUserId = subjectLikedBO.getLikeUserId();
//        String hashKey = subjectId + ":" + likeUserId;
        // 保存题目与点赞用户的信息到Redis
//        redisTemplate.opsForHash().put(SUBJECT_LIKED_PREFIX, hashKey, status);

        // MQ发送点赞消息
        SubjectLikedMessage message = SubjectLikedMessage.builder()
                .SubjectId(subjectId)
                .likedUserId(likeUserId)
                .status(status)
                .build();
        rocketMQTemplate.convertAndSend("subject-liked", JSON.toJSONString(message));
        String countKey = SUBJECT_LIKED_COUNT_PREFIX + "." + subjectId;
        String detailKey = SUBJECT_LIKED_DETAIL_KEY + "." + subjectId + "." + likeUserId;
        if (status == SubjectLikedStatusEnum.LIKED.getStatus()) {
            // 如果是点赞操作，对应题目点赞数+1
            redisTemplate.opsForValue().increment(countKey, 1);
            redisTemplate.opsForValue().set(detailKey, "1");
        } else {
            // 如果是取消点赞操作，对应题目点赞数-1
            Integer count = (Integer) redisTemplate.opsForValue().get(countKey);
            if (count == null || count == 0) {
                return;
            }
            redisTemplate.opsForValue().decrement(countKey, 1);
            redisTemplate.delete(detailKey);
        }
    }

    @Override
    public Boolean isLiked(String subjectId, String userId) {
        String detailKey = SUBJECT_LIKED_DETAIL_KEY + "." + subjectId + "." + userId;
        return redisTemplate.hasKey(detailKey);
    }

    @Override
    public Integer getLikedCount(String subjectId) {
        String countKey = SUBJECT_LIKED_COUNT_PREFIX + "." + subjectId;
        Integer count = (Integer) redisTemplate.opsForValue().get(countKey);
        if (Objects.isNull(count) || count <= 0) {
            return 0;
        }
        return count;
    }

    @Override
    public void syncLiked() {
        Map<Object, Object> map = new HashMap<>();
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(SUBJECT_LIKED_PREFIX, ScanOptions.NONE);
        while (cursor.hasNext()) {
            Map.Entry<Object, Object> entry = cursor.next();
            Object hashKey = entry.getKey();
            Object hashValue = entry.getValue();
            map.put(hashKey, hashValue);
            redisTemplate.opsForHash().delete(SUBJECT_LIKED_PREFIX, hashKey);
        }
        log.info("syncLiked.subjectLikedMap:{}", JSON.toJSONString(map));
        List<SubjectLiked> list = new ArrayList<>(map.size());
        map.forEach((key, value) -> {
            SubjectLiked subjectLiked = new SubjectLiked();
            String[] arr = key.toString().split(":");
            subjectLiked.setSubjectId(Long.valueOf(arr[0]));
            subjectLiked.setLikeUserId(arr[1]);
            subjectLiked.setStatus(Integer.valueOf(value.toString()));
            list.add(subjectLiked);
        });
        subjectLikedService.saveBatch(list);
    }

    @Override
    public PageDTO<SubjectLikedBO> getSubjectLikedPage(SubjectLikedBO subjectLikedBO) {
        String userId = subjectLikedBO.getLikeUserId();
        Page<SubjectLiked> page = subjectLikedService.getSubjectLikedList(userId, subjectLikedBO.toMpPage());
        // 得到题目ID列表
//        List<Long> idList = page.getRecords().stream()
//                .map(SubjectLiked::getSubjectId)
//                .collect(Collectors.toList());
        return PageDTO.of(page, subjectLiked -> {
            SubjectLikedBO bo = BeanUtil.copyProperties(subjectLiked, SubjectLikedBO.class);
            SubjectInfo subjectInfo = subjectInfoService.getById(bo.getSubjectId());
            bo.setSubjectName(subjectInfo.getSubjectName());
            return bo;
        });
    }

    @Override
    public void syncByMessage(SubjectLikedBO bo) {
        SubjectLiked subjectLiked = SubjectLiked.builder()
                .subjectId(bo.getSubjectId())
                .likeUserId(bo.getLikeUserId())
                .status(bo.getStatus())
                .build();
        subjectLikedService.save(subjectLiked);
    }
}
